"""
提示词优化和验证模块

提供提示词模板的优化建议、质量评估和自动选择功能。
"""

from typing import Dict, List, Optional, Tuple, Any
import re
from dataclasses import dataclass

from .types import PromptTemplate, PromptStyle, PromptUsageStats


@dataclass
class OptimizationSuggestion:
    """优化建议"""
    template_name: str
    suggestion_type: str  # "style", "structure", "variables", "performance"
    description: str
    priority: str  # "high", "medium", "low"
    impact: str  # 描述预期影响


@dataclass
class TemplateQualityMetrics:
    """模板质量指标"""
    clarity_score: float  # 清晰度得分
    efficiency_score: float  # 效率得分
    flexibility_score: float  # 灵活性得分
    overall_score: float  # 综合得分
    strengths: List[str]  # 优势
    weaknesses: List[str]  # 弱点
    recommendations: List[str]  # 改进建议


class PromptOptimizer:
    """
    提示词优化器

    提供模板质量评估、优化建议和自动选择功能。
    """

    def __init__(self):
        """初始化提示词优化器"""
        self.usage_stats = {}  # 模板使用统计

    def analyze_template_quality(self, template: PromptTemplate) -> TemplateQualityMetrics:
        """
        分析模板质量

        Args:
            template: 要分析的模板

        Returns:
            TemplateQualityMetrics: 质量分析结果
        """
        # 清晰度评估
        clarity_score = self._evaluate_clarity(template)

        # 效率评估
        efficiency_score = self._evaluate_efficiency(template)

        # 灵活性评估
        flexibility_score = self._evaluate_flexibility(template)

        # 综合得分
        overall_score = (clarity_score + efficiency_score + flexibility_score) / 3

        # 优势和弱点分析
        strengths, weaknesses = self._analyze_strengths_weaknesses(
            template, clarity_score, efficiency_score, flexibility_score
        )

        # 生成改进建议
        recommendations = self._generate_recommendations(
            template, clarity_score, efficiency_score, flexibility_score
        )

        return TemplateQualityMetrics(
            clarity_score=clarity_score,
            efficiency_score=efficiency_score,
            flexibility_score=flexibility_score,
            overall_score=overall_score,
            strengths=strengths,
            weaknesses=weaknesses,
            recommendations=recommendations
        )

    def _evaluate_clarity(self, template: PromptTemplate) -> float:
        """评估模板清晰度"""
        score = 1.0
        factors = []

        # 结构清晰度（基于标题和分隔符）
        structure_markers = ['【', '】', '---', '\n\n']
        structure_count = sum(template.template.count(marker) for marker in structure_markers)
        structure_score = min(structure_count / 10, 1.0)
        factors.append(structure_score)

        # 指令明确度（基于明确的指令词）
        instruction_words = ['请', '需要', '要求', '必须', '应该', '确保']
        instruction_count = sum(template.template.count(word) for word in instruction_words)
        instruction_score = min(instruction_count / 5, 1.0)
        factors.append(instruction_score)

        # 变量命名清晰度
        clear_var_names = ['context', 'question', 'input', 'text', 'content']
        clear_var_count = sum(1 for var in template.required_vars if var in clear_var_names)
        var_score = clear_var_count / len(template.required_vars) if template.required_vars else 1.0
        factors.append(var_score)

        return sum(factors) / len(factors)

    def _evaluate_efficiency(self, template: PromptTemplate) -> float:
        """评估模板效率"""
        score = 1.0
        factors = []

        # 长度效率（模板长度适中）
        template_length = len(template.template)
        optimal_length = 500  # 理想长度
        length_diff = abs(template_length - optimal_length)
        length_score = max(0, 1 - length_diff / optimal_length)
        factors.append(length_score)

        # 变量使用效率（避免冗余变量）
        used_vars = set(re.findall(r'\{(\w+)\}', template.template))
        redundant_vars = len(template.required_vars) - len(used_vars)
        var_efficiency = max(0, 1 - redundant_vars / len(template.required_vars)) if template.required_vars else 1.0
        factors.append(var_efficiency)

        # 复杂度效率（避免过度复杂的结构）
        complexity_score = 1.0 - template.get_complexity_score()
        factors.append(complexity_score)

        return sum(factors) / len(factors)

    def _evaluate_flexibility(self, template: PromptTemplate) -> float:
        """评估模板灵活性"""
        score = 1.0
        factors = []

        # 变量灵活性（支持可选变量）
        optional_ratio = len(template.optional_vars) / (len(template.required_vars) + len(template.optional_vars))
        optional_score = min(optional_ratio, 0.5) + 0.5  # 可选变量占比，但不占主导
        factors.append(optional_score)

        # 风格适应性（基于模板的设计）
        style_adaptability = self._evaluate_style_adaptability(template)
        factors.append(style_adaptability)

        # 场景适应性（基于元数据）
        scenario_score = 1.0
        if template.metadata:
            scenario_tags = template.metadata.get('best_for', 'general')
            scenario_score = 0.8 if scenario_tags != 'general' else 1.0
        factors.append(scenario_score)

        return sum(factors) / len(factors)

    def _evaluate_style_adaptability(self, template: PromptTemplate) -> float:
        """评估风格适应性"""
        # 检查模板是否包含风格中性词汇
        neutral_words = ['分析', '回答', '处理', '解决', '提供']
        neutral_count = sum(template.template.count(word) for word in neutral_words)

        # 检查是否避免过于特定的风格词汇
        style_specific_words = ['亲爱的', '尊敬的', '哈哈', '呵呵']
        style_specific_count = sum(template.template.count(word) for word in style_specific_words)

        base_score = 0.7
        neutral_bonus = min(neutral_count / 5, 0.2)
        style_penalty = min(style_specific_count / 3, 0.2)

        return base_score + neutral_bonus - style_penalty

    def _analyze_strengths_weaknesses(
        self,
        template: PromptTemplate,
        clarity: float,
        efficiency: float,
        flexibility: float
    ) -> Tuple[List[str], List[str]]:
        """分析优势和弱点"""
        strengths = []
        weaknesses = []

        # 清晰度分析
        if clarity >= 0.8:
            strengths.append("结构清晰，指令明确")
        elif clarity < 0.5:
            weaknesses.append("模板结构不够清晰，指令不够明确")

        # 效率分析
        if efficiency >= 0.8:
            strengths.append("模板长度适中，使用效率高")
        elif efficiency < 0.5:
            weaknesses.append("模板可能过长或包含冗余内容")

        # 灵活性分析
        if flexibility >= 0.8:
            strengths.append("模板灵活性强，适应性好")
        elif flexibility < 0.5:
            weaknesses.append("模板灵活性不足，适用场景有限")

        # 其他基于具体特征的分析
        if len(template.required_vars) <= 3:
            strengths.append("变量设计简洁，易于使用")
        elif len(template.required_vars) > 6:
            weaknesses.append("变量数量过多，可能增加使用复杂度")

        if len(template.examples) > 0:
            strengths.append("提供了使用示例，便于理解")
        else:
            weaknesses.append("缺少使用示例，新用户可能不易上手")

        return strengths, weaknesses

    def _generate_recommendations(
        self,
        template: PromptTemplate,
        clarity: float,
        efficiency: float,
        flexibility: float
    ) -> List[str]:
        """生成改进建议"""
        recommendations = []

        # 清晰度改进建议
        if clarity < 0.6:
            recommendations.append("增加清晰的结构标记（如【】符号）")
            recommendations.append("添加更明确的指令词汇")
            recommendations.append("使用更清晰的变量命名")

        # 效率改进建议
        if efficiency < 0.6:
            recommendations.append("精简模板内容，去除冗余信息")
            recommendations.append("优化变量使用，避免未使用的变量")
            recommendations.append("简化复杂的模板结构")

        # 灵活性改进建议
        if flexibility < 0.6:
            recommendations.append("增加可选变量支持")
            recommendations.append("使用更中性的语言风格")
            recommendations.append("扩展适用的场景范围")

        # 通用改进建议
        if not template.examples:
            recommendations.append("添加使用示例和说明")
        if not template.metadata:
            recommendations.append("完善模板元数据信息")

        return recommendations

    def suggest_optimal_template(
        self,
        templates: Dict[str, PromptTemplate],
        context: Dict[str, Any]
    ) -> Tuple[str, float, str]:
        """
        为给定上下文建议最优模板

        Args:
            templates: 可用模板字典
            context: 上下文信息

        Returns:
            Tuple[str, float, str]: (模板名称, 得分, 推荐理由)
        """
        best_template = None
        best_score = 0
        best_reason = ""

        for name, template in templates.items():
            score, reason = self._calculate_template_score(template, context)
            if score > best_score:
                best_score = score
                best_template = name
                best_reason = reason

        return best_template, best_score, best_reason

    def _calculate_template_score(self, template: PromptTemplate, context: Dict[str, Any]) -> Tuple[float, str]:
        """计算模板得分"""
        score = 0.0
        reasons = []

        # 上下文长度匹配
        context_length = context.get('context_length', 0)
        if template.style.is_suitable_for_context_length(context_length):
            score += 0.3
            reasons.append(f"风格{template.style.value}适合{context_length}字符的上下文")
        else:
            reasons.append(f"风格可能不适合当前上下文长度")

        # 风格匹配
        preferred_style = context.get('preferred_style')
        if preferred_style and template.style == preferred_style:
            score += 0.2
            reasons.append(f"匹配用户偏好的{preferred_style.value}风格")

        # 分类匹配
        category = context.get('category')
        if category and template.metadata and template.metadata.get('category') == category:
            score += 0.3
            reasons.append(f"模板分类与需求匹配")

        # 复杂度匹配
        complexity_preference = context.get('complexity', 'medium')
        template_complexity = template.get_complexity_score()
        if complexity_preference == 'low' and template_complexity < 0.4:
            score += 0.1
            reasons.append("模板复杂度适合快速响应")
        elif complexity_preference == 'high' and template_complexity > 0.6:
            score += 0.1
            reasons.append("模板复杂度适合深度分析")

        # 历史表现（如果有使用统计）
        if template.name in self.usage_stats:
            stats = self.usage_stats[template.name]
            performance_score = stats.success_rate * 0.1
            score += performance_score
            reasons.append(f"历史成功率{stats.success_rate:.1%}")

        reason_str = "; ".join(reasons) if reasons else "通用模板"
        return score, reason_str

    def record_usage(
        self,
        template_name: str,
        response_length: int,
        success: bool = True,
        satisfaction: Optional[float] = None
    ) -> None:
        """
        记录模板使用情况

        Args:
            template_name: 模板名称
            response_length: 响应长度
            success: 是否成功
            satisfaction: 用户满意度
        """
        if template_name not in self.usage_stats:
            self.usage_stats[template_name] = PromptUsageStats(template_name=template_name)

        self.usage_stats[template_name].update_usage(response_length, success, satisfaction)

    def get_usage_statistics(self) -> Dict[str, PromptUsageStats]:
        """获取使用统计"""
        return self.usage_stats.copy()

    def get_performance_report(self) -> Dict[str, Any]:
        """获取性能报告"""
        if not self.usage_stats:
            return {"message": "暂无使用数据"}

        # 计算总体统计
        total_usage = sum(stats.usage_count for stats in self.usage_stats.values())
        avg_success_rate = sum(
            stats.success_rate * stats.usage_count for stats in self.usage_stats.values()
        ) / total_usage if total_usage > 0 else 0

        # 找出最佳和最差表现
        best_template = max(
            self.usage_stats.items(),
            key=lambda x: x[1].success_rate
        )
        worst_template = min(
            self.usage_stats.items(),
            key=lambda x: x[1].success_rate
        )

        # 使用频率排行
        most_used = max(
            self.usage_stats.items(),
            key=lambda x: x[1].usage_count
        )

        return {
            "total_usage": total_usage,
            "avg_success_rate": round(avg_success_rate, 3),
            "best_performer": {
                "template": best_template[0],
                "success_rate": round(best_template[1].success_rate, 3),
                "usage_count": best_template[1].usage_count
            },
            "worst_performer": {
                "template": worst_template[0],
                "success_rate": round(worst_template[1].success_rate, 3),
                "usage_count": worst_template[1].usage_count
            },
            "most_used": {
                "template": most_used[0],
                "usage_count": most_used[1].usage_count,
                "success_rate": round(most_used[1].success_rate, 3)
            }
        }

    def generate_optimization_suggestions(self, templates: Dict[str, PromptTemplate]) -> List[OptimizationSuggestion]:
        """
        生成优化建议

        Args:
            templates: 模板字典

        Returns:
            List[OptimizationSuggestion]: 优化建议列表
        """
        suggestions = []

        for name, template in templates.items():
            quality = self.analyze_template_quality(template)

            # 基于质量得分生成建议
            if quality.clarity_score < 0.6:
                suggestions.append(OptimizationSuggestion(
                    template_name=name,
                    suggestion_type="structure",
                    description="改进模板结构，增加清晰的标记和分隔符",
                    priority="high",
                    impact="显著提升回答质量和一致性"
                ))

            if quality.efficiency_score < 0.6:
                suggestions.append(OptimizationSuggestion(
                    template_name=name,
                    suggestion_type="performance",
                    description="精简模板内容，优化变量使用",
                    priority="medium",
                    impact="提高响应速度和资源利用率"
                ))

            if quality.flexibility_score < 0.6:
                suggestions.append(OptimizationSuggestion(
                    template_name=name,
                    suggestion_type="variables",
                    description="增加可选变量支持，提高模板适应性",
                    priority="medium",
                    impact="扩大模板适用范围"
                ))

            # 基于使用统计生成建议
            if name in self.usage_stats:
                stats = self.usage_stats[name]
                if stats.success_rate < 0.7:
                    suggestions.append(OptimizationSuggestion(
                        template_name=name,
                        suggestion_type="performance",
                        description=f"模板成功率较低({stats.success_rate:.1%})，建议重新设计或优化",
                        priority="high",
                        impact="显著提升用户满意度"
                    ))

        # 按优先级排序
        priority_order = {"high": 3, "medium": 2, "low": 1}
        suggestions.sort(key=lambda x: priority_order.get(x.priority, 0), reverse=True)

        return suggestions